package org.example.chatroom.demos.socket;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.example.chatroom.demos.component.OnlineUserManager;
import org.example.chatroom.demos.mapper.MessageMapper;
import org.example.chatroom.demos.mapper.MessageSessionMapper;
import org.example.chatroom.demos.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


@Component
@Slf4j
public class WebsocketApi  extends TextWebSocketHandler {

    @Autowired
    private OnlineUserManager onlineUserManager ;

//      处理json字符串
    private ObjectMapper objectMapper = new ObjectMapper() ;

    @Autowired
    private MessageSessionMapper messageSessionMapper ;

    @Autowired
    private MessageMapper messageMapper ;


    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//      获取 登录用户的userId
        User user = (User) session.getAttributes().get("USER_KEY");
        if(user == null){
            return;
        }
         onlineUserManager.online(user.getId() , session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
      log.info("收到消息");
//      后面这个处理收到的消息
        // 获取 登录用户的userId
        User user = (User) session.getAttributes().get("USER_KEY");
        if(user == null){
            log.info("无法获得当前登录用户");
            return;
        }

//        处理请求, 首先请求过来的类型要符合我们设定的类型
//         把json字符串转成对应的对象 ;
        RequestMessage requestMessage = objectMapper.readValue(message.getPayload(), RequestMessage.class);

//         处理请求,转发响应
          transmitMessage(user ,requestMessage );
    }

    private void transmitMessage(User fromUser, RequestMessage request) throws IOException {
//        判断 请求格式是否正确
        if(!request.getType().equals("message")){
            log.info("请求的格式不符合:message类型");
            return;
        }
           // 1. 构造出响应对象
        ResponseMessage responseMessage = new ResponseMessage() ;
        responseMessage.setFromId(fromUser.getId());
        responseMessage.setFromName(fromUser.getUserName());
        responseMessage.setContent(request.getContent());
        responseMessage.setSessionId(request.getSessionId());

        // 2. 还要把对象转成json字符串,才能发送
        String respJson = objectMapper.writeValueAsString(responseMessage);
        log.info("构造出Response: "+respJson);

//        3. 获取要发送给哪个用户 ;
          Friend targetFriend =messageSessionMapper.getFriendBySessionId(responseMessage.getSessionId(), fromUser.getId());
           Friend myself = new Friend() ;
//           还要给自己发一份
           myself.setFriendId(fromUser.getId());
          List<Friend> friends = new ArrayList<>() ;
          friends.add(targetFriend) ;
          friends.add(myself) ;
//                    使用send发送消息,还要把消息包装成TextMessage对象
            for(Friend friend : friends){
              WebSocketSession webSocketSession = onlineUserManager.getSession(friend.getFriendId());
//              如果当前用户没有上线就不发
                if( webSocketSession != null){
                    webSocketSession.sendMessage(new TextMessage(respJson));
                }
            }

            // 4. 把消息保存到数据库 就是 往message表里插入信息 ;
//        生成message对象
        Message message =  new Message() ;
            // 主键和时间都可以通过sql
            message.setFromId(responseMessage.getFromId());
            message.setSessionId(responseMessage.getSessionId());
            message.setContent(responseMessage.getContent());

            // 插入数据
          Integer result =  messageMapper.add(message);

//          插入数据后还要跟新会话的lastTime

          if(result < 1){
              log.error("message数据插入失败"+message);
          }else {
              messageMapper.updateSessionLastTime(message.getSessionId()) ;
              log.info("message数据插入成功"+message);
          }

    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
      // 获取 登录用户的userId
        User user = (User) session.getAttributes().get("USER_KEY");
        if(user == null){
            return;
        }
         log.error("连接发生异常:",exception);
        onlineUserManager.downLine(user.getId() , session);
     }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
       // 获取 登录用户的userId
        User user = (User) session.getAttributes().get("USER_KEY");
        if(user == null){
            return;
        }
        onlineUserManager.downLine(user.getId() , session);
    }
}
